from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, status, BackgroundTasks
from typing import Dict, Optional
from app.services.file_service import FileService
from app.core.logger import logger
from app.models.file import FileUploadResponse, FileErrorResponse
from app.core.exceptions import FileUploadError
import traceback

router = APIRouter(tags=["文件管理"])

# 依赖项：创建FileService实例
def get_file_service():
    return FileService()

@router.post(
    "/files/upload", 
    response_model=FileUploadResponse,
    responses={
        400: {"model": FileErrorResponse, "description": "请求参数错误"},
        413: {"model": FileErrorResponse, "description": "文件太大"},
        415: {"model": FileErrorResponse, "description": "不支持的文件类型"},
        500: {"model": FileErrorResponse, "description": "服务器内部错误"},
        503: {"model": FileErrorResponse, "description": "存储服务不可用"}
    }
)
async def upload_file(
    background_tasks: BackgroundTasks,
    file: UploadFile = File(..., description="要上传的文件"),
    user: str = Form(..., description="用户标识"),
    file_service: FileService = Depends(get_file_service)
):
    """
    上传文件
    
    上传文件并在发送消息时使用，可实现图文多模态理解。
    支持您的应用程序所支持的所有格式。上传的文件仅供当前终端用户使用。
    
    可能的错误:
    - 400: no_file_uploaded - 必须提供文件
    - 400: too_many_files - 目前只接受一个文件 
    - 400: unsupported_preview - 该文件不支持预览
    - 400: unsupported_estimate - 该文件不支持估算
    - 413: file_too_large - 文件太大 
    - 415: unsupported_file_type - 不支持的扩展名
    - 503: s3_connection_failed - 无法连接到存储服务
    - 503: s3_permission_denied - 无权限上传文件
    - 503: s3_file_too_large - 文件超出存储大小限制
    """
    logger.debug(f"收到文件上传请求: filename={file.filename}, user={user}")
    
    # 验证用户ID
    if not user or not user.strip():
        logger.warning(f"用户ID为空: {user}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "error": "用户ID不能为空",
                "error_code": "invalid_user",
                "status": "error"
            }
        )
    
    # 验证文件
    if not file or not file.filename:
        logger.warning("文件为空或文件名为空")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "error": "必须提供文件",
                "error_code": "no_file_uploaded",
                "status": "error"
            }
        )
    
    # 读取文件内容进行初步验证
    try:
        # 确保文件大小不为零
        content = await file.read()
        if len(content) == 0:
            logger.warning("上传了空文件")
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail={
                    "error": "不能上传空文件",
                    "error_code": "empty_file",
                    "status": "error"
                }
            )
        
        # 重置文件读取位置，准备发送给服务
        await file.seek(0)
        
    except Exception as e:
        logger.error(f"读取文件内容时出错: {str(e)}")
        logger.error(traceback.format_exc())
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "error": f"读取文件内容时出错: {str(e)}",
                "error_code": "file_read_error",
                "status": "error"
            }
        )
    
    try:
        # 调用文件服务上传文件
        result = await file_service.upload_file(
            file=file,
            user=user
        )
        
        # 确保返回数据符合FileUploadResponse模型
        if "created_by" not in result:
            result["created_by"] = user  # 如果API没有返回created_by字段，使用user作为默认值
            
        # 异步清理临时文件
        def clean_temp_file():
            try:
                file.file.close()
                logger.debug(f"已关闭临时文件: {file.filename}")
            except Exception as e:
                logger.error(f"关闭临时文件失败: {str(e)}")
        
        background_tasks.add_task(clean_temp_file)
            
        return result
    except FileUploadError as e:
        # 文件上传错误由FileService抛出，包含了详细信息
        logger.error(f"文件上传失败: {str(e)}")
        status_code = e.status_code if hasattr(e, 'status_code') else status.HTTP_500_INTERNAL_SERVER_ERROR
        error_data = e.error_data if hasattr(e, 'error_data') else {}
        
        raise HTTPException(
            status_code=status_code,
            detail=error_data or {
                "error": str(e),
                "error_code": getattr(e, 'error_code', "file_upload_error"),
                "status": "error"
            }
        )
    except Exception as e:
        # 其他未预期的错误
        logger.error(f"上传文件时发生未知错误: {str(e)}")
        logger.error(traceback.format_exc())
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail={
                "error": f"上传文件失败: {str(e)}",
                "error_code": "unknown_error",
                "status": "error"
            }
        )
